/*
 * Timer.h
 *
 *	Author: stravant
 *	Description:
 *		
 */

#ifndef TIMER_H_
#define TIMER_H_

#include "Time.h"
#include "EventLoop.h"

namespace tbt {

/*
 * Simple class for keeping track of an elapsed time.
 * Resetting the |Timer| sets it's elapsed to 0, elapsed
 * returns the time that has passed since the last reset.
 */
class Timer {
public:
	Timer();
	~Timer();

	void reset();
	TimeDelta elapsed() const;

private:
	Time mTime;
};



/*
 * A ticker class which manages the lifetime of a |Task|
 * in a given event loop. Classes should inheret from this
 * rather than an |Task| if they have a lifetime shorter
 * than that of the event loop.
 */
class Ticker {
public:
	Ticker(Ref<EventLoop> eventLoop = EventLoop::current());
	virtual ~Ticker();

	virtual void tick(Time time) = 0;

private:
	class Ticker_Task: public Task {
	public:
		Ticker_Task(Ticker* target): mTarget(target) {}
		~Ticker_Task() {
			//If the event loop is destroyed before the Ticker,
			//shouldn't happen but better be safe.
			if (mTarget)
				mTarget->mTask = nullptr;
		}
		virtual bool tick(Time t) {
			if (mTarget) {
				mTarget->tick(t);
				return false;
			} else {
				return true;
			}
		}
		void kill() {mTarget = nullptr; }
	private:
		Ticker* mTarget;
	};

	friend class Ticker_Task;
	Ticker_Task* mTask;
};


/*
 * A Ticker which calls to the override of periodicTick periodically.
 * periodicTick is gauranteed to be called at at least once for every
 * |period| passed, even if more than one passes between iterations of
 * the main loop. As a result, the |time| passsed to |periodicTick| is
 * not nessecarily accurate to within one |period|.
 */
class TickerPeriodic: private Ticker {
public:
	TickerPeriodic(TimeDelta period, Ref<EventLoop> eventLoop = EventLoop::current());
	virtual ~TickerPeriodic();

	virtual void periodicTick(Time time) = 0;

	void start() {mLastTick = Time::Now(); mIsRunning = true; }
	void stop() {mIsRunning = false; }

protected:
	void setPeriod(TimeDelta period) {
		mPeriod = period;
		if (mIsRunning)
			start();
	}

private:
	virtual void tick(Time t);

private:
	bool mIsRunning;
	Time mLastTick;
	TimeDelta mPeriod;
};

}

#endif /* TIMER_H_ */

























